﻿using System;
using System.Collections.Generic;
using AForge.Video.FFMPEG;
using System.IO;
using System.Drawing.Imaging;

namespace VideoCoreWCF {
    public class VideoCacheProvider {
        private static VideoCacheProvider m_current;
        private Dictionary<string, VideoTrancodeReader> m_frames;
        /// <summary>
        /// Prevents a default instance of the <see cref="VideoCacheProvider"/> class from being created.
        /// </summary>
        private VideoCacheProvider() {
            m_frames = new Dictionary<string, VideoTrancodeReader>();
        }
        private static object m_locker = new object();
        /// <summary>
        /// Gets the current.
        /// </summary>
        public static VideoCacheProvider Current {
            get {
                if (m_current == null) {
                    lock (m_locker) {
                        if (m_current == null) {
                            m_current = new VideoCacheProvider();
                        }
                    }
                }
                return m_current;
            }
        }

        /// <summary>
        /// Gets the frame.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        /// <param name="frameNo">The frame no.</param>
        /// <returns></returns>
        public byte[] GetFrame(string fileName, long frameNo) {
            VideoTrancodeReader reader = null;
            if (!m_frames.TryGetValue(fileName, out reader)) {
                reader = new VideoTrancodeReader(FileHelper.GetFullFileName(fileName));
                m_frames.Add(fileName, reader);
            }
            var bitmap = reader.GetFrame(frameNo);
            using (MemoryStream ms = new MemoryStream()) {
                bitmap.Save(ms, ImageFormat.Jpeg);
                return ms.ToArray();
            }
        }
        /// <summary>
        /// Gets the file info.
        /// </summary>
        /// <param name="fileName">Filename in format [CameraIP/DateTime/starttime_endtime.extension].</param>
        /// <returns></returns>
        public VideoFileInfo GetFileInfo(string fileName) {
            using (VideoFileReader videoReader = new VideoFileReader()) {
                VideoFileInfo item = GetItem(videoReader, fileName);
                long frameCount = 0;
                if (item.FrameLength == 0) {
                    while (videoReader.ReadVideoFrame() != null) {
                        frameCount++;
                    }
                    item.FrameLength = frameCount;
                }

                videoReader.Close();
                return item;
            }
        }

        /// <summary>
        /// Gets the item.
        /// </summary>
        /// <param name="videoReader">The video reader.</param>
        /// <param name="fileName">Name of the file.</param>
        /// <returns></returns>
        private VideoFileInfo GetItem(VideoFileReader videoReader, string fileName){
            videoReader.Open(FileHelper.GetFullFileName(fileName));
            var item = new VideoFileInfo {
                                             Name = fileName,
                                             FrameLength = videoReader.FrameCount,
                                             Durations = videoReader.FrameRate,
                                             Width = videoReader.Width,
                                             Height = videoReader.Height
                                         };
            string sName = fileName.Substring(fileName.LastIndexOf(@"\") + 1, fileName.LastIndexOf(".") - fileName.LastIndexOf(@"\"));
            
            item.StartTime = new TimeSpan(
                int.Parse(sName.Substring(0, 2)),
                int.Parse(sName.Substring(2, 2)),
                int.Parse(sName.Substring(4, 2)));
            sName = FileHelper.GetNextFile(string.Empty, fileName);
            if (sName != string.Empty){
                sName = sName.Substring(sName.LastIndexOf(@"\") + 1, sName.LastIndexOf(".") - sName.LastIndexOf(@"\"));
                item.EndTime = new TimeSpan(
                    int.Parse(sName.Substring(0, 2)),
                    int.Parse(sName.Substring(2, 2)),
                    int.Parse(sName.Substring(4, 2)));
            }
            return item;    
        }
    }
}
